package com.yixing.tech.common.utils;

import com.yixing.tech.common.service.CommonService;
import lombok.extern.slf4j.Slf4j;

import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
public class CommonUtil {

    public static final String RANDOM_STRING = "0123456789abcdefghijklmnopqrstuvwxyz";

    public static final String LOGIN_NAME_PATTERN = "^[a-zA-Z0-9_]{4,20}$";

    public static final String EMAIL_PATTERN = "^[_A-Za-z0-9-]+(\\.[_A-Za-z0-9-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*(\\.[A-Za-z]{2,})$";

    public static final String PHONE_PATTERN = "^1(3[0-9]|4[01456879]|5[0-9]|6[2567]|7[0-8]|8[0-9]|9[0-9])\\d{8}$";


    /**
     * 判断字符串是否为空
     *
     * @param text
     * @return
     */
    public static boolean stringIsBlank(Object text) {
        return text == null || text.toString().length() == 0;

    }

    public static boolean checkPhone(String context) {
        return Pattern.matches(PHONE_PATTERN, context);
    }

    /**
     * 前部追加某个字符串
     *
     * @param text
     * @param length
     * @return
     */
    public static String appendText(String text, int length, String appendText) {
        if (text.length() >= length) {
            return text;
        }
        int num = length - text.length();
        for (int i = 0; i < num; i++) {
            text = appendText + text;
        }
        return text;

    }

    public static int parseInt(String text) {
        try {
            return Integer.parseInt(text);
        } catch (NumberFormatException e) {
            return 0;
        }
    }

    /**
     * string 转int
     *
     * @param text
     * @return
     */
    public static int stringPraseInt(String text) {
        try {
            int result = Integer.parseInt(text);
            return result;
        } catch (NumberFormatException e) {
            return 0;
        }

    }

    public static long parseLong(String text) {
        try {
            return Long.parseLong(text);
        } catch (NumberFormatException e) {
            return 0L;
        }

    }

    /**
     * 判断list是否为空
     *
     * @param list
     * @return
     */
    public static boolean listIsBlank(Collection list) {
        return (list == null || list.size() == 0);
    }

    /**
     * 判断map是否为空
     *
     * @param map
     * @return
     */
    public static boolean mapIsBlank(Map map) {
        return (map == null || map.size() == 0);
    }

    /**
     * 获取随机数
     *
     * @param num
     * @return
     */
    public static String getRandomCode(int num) {
        String code = "";
        Random random = new Random();
        for (int i = 0; i < num; i++) {
            code += random.nextInt(10) + "";
        }

        return code;

    }

    public static String getRandomStringCode(int num) {
        String code = "";
        Random random = new Random();
        for (int i = 0; i < num; i++) {
            code += RANDOM_STRING.charAt(random.nextInt(RANDOM_STRING.length() - 1));
        }
        return code;

    }


    /**
     * 获取uuid
     *
     * @return
     */
    public static String createUuid() {

        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    /**
     * 判断descBytes 在 srcBytes 的位置
     *
     * @param srcBytes
     * @param descBytes
     * @return
     */
    public static int indexOfBytes(byte[] srcBytes, byte[] descBytes) {
        for (int i = 0; i < srcBytes.length - descBytes.length + 1; i++) {
            for (int j = 0; j < descBytes.length; j++) {
                if (srcBytes[i + j] != descBytes[j]) {
                    break;
                }
                if (j == descBytes.length - 1) {
                    return i;
                }
            }
        }
        return -1;

    }

    public static int lastIndexOfBytes(byte[] srcBytes, byte[] descBytes) {
        int result = -1;
        for (int i = 0; i < srcBytes.length - descBytes.length + 1; i++) {
            for (int j = 0; j < descBytes.length; j++) {
                if (srcBytes[i + j] != descBytes[j]) {
                    break;
                }
                if (j == descBytes.length - 1) {
                    result = i;
                }
            }
        }
        return result;

    }

    public static List<String> stringToList(String text) {
        if (stringIsBlank(text)) {
            return null;
        }
        String[] arr = text.trim().split(" ");
        List<String> list = new ArrayList<>();
        for (int i = 0; i < arr.length; i++) {
            if (!CommonUtil.stringIsBlank(String.valueOf(arr[i]).trim())) {
                list.add(arr[i].trim());
            }
        }
        if (list.size() == 0) {
            return null;
        }
        return list;
    }


    public static String unicodeToAscii(String str) {
        if (str == null) {
            return "";
        }
        Pattern pattern = Pattern.compile("\\&\\#(\\d+)\\;");
        Matcher m = pattern.matcher(str);
        Map<String, String> maps = new HashMap<String, String>();
        while (m.find()) {
            int temp = Integer.valueOf(m.group(1)).intValue();
            maps.put("&#" + temp + ";", String.valueOf((char) temp));
        }
        Iterator<Map.Entry<String, String>> iterator = maps.entrySet()
                .iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            str = str.replaceAll(entry.getKey(), entry.getValue());
        }
        return str;

    }


    public static String urlEecoder(String text) {
        try {
            text = URLEncoder.encode(text, "utf-8");
            return text;
        } catch (UnsupportedEncodingException e) {
        }
        return text;
    }

    public static boolean judgeFromWechat(String userAgent) {
        if (userAgent.toLowerCase().contains("micromessenger")) {
            return true;
        }
        return false;
    }

    public static boolean JudgeIsMoblie(String userAgent) {

        boolean isMoblie = false;
        String[] mobileAgents = {"iphone", "android", "ipad", "phone", "mobile", "wap", "netfront", "java", "opera mobi",
                "opera mini", "ucweb", "windows ce", "symbian", "series", "webos", "sony", "blackberry", "dopod",
                "nokia", "samsung", "palmsource", "xda", "pieplus", "meizu", "midp", "cldc", "motorola", "foma",
                "docomo", "up.browser", "up.link", "blazer", "helio", "hosin", "huawei", "novarra", "coolpad", "webos",
                "techfaith", "palmsource", "alcatel", "amoi", "ktouch", "nexian", "ericsson", "philips", "sagem",
                "wellcom", "bunjalloo", "maui", "smartphone", "iemobile", "spice", "bird", "zte-", "longcos",
                "pantech", "gionee", "portalmmm", "jig browser", "hiptop", "benq", "haier", "^lct", "320x320",
                "240x320", "176x220", "w3c ", "acs-", "alav", "alca", "amoi", "audi", "avan", "benq", "bird", "blac",
                "blaz", "brew", "cell", "cldc", "cmd-", "dang", "doco", "eric", "hipt", "inno", "ipaq", "java", "jigs",
                "kddi", "keji", "leno", "lg-c", "lg-d", "lg-g", "lge-", "maui", "maxo", "midp", "mits", "mmef", "mobi",
                "mot-", "moto", "mwbp", "nec-", "newt", "noki", "oper", "palm", "pana", "pant", "phil", "play", "port",
                "prox", "qwap", "sage", "sams", "sany", "sch-", "sec-", "send", "seri", "sgh-", "shar", "sie-", "siem",
                "smal", "smar", "sony", "sph-", "symb", "t-mo", "teli", "tim-", "tosh", "tsm-", "upg1", "upsi", "vk-v",
                "voda", "wap-", "wapa", "wapi", "wapp", "wapr", "webc", "winw", "winw", "xda", "xda-",
                "Googlebot-Mobile"};
        for (String mobileAgent : mobileAgents) {
            if (userAgent.toLowerCase().indexOf(mobileAgent) >= 0
                    && userAgent.toLowerCase().indexOf("windows nt") <= 0 &&
                    userAgent.toLowerCase().indexOf("macintosh") <= 0) {
                isMoblie = true;
                break;
            }
        }
        return isMoblie;
    }

    public static double roundDouble(double temp) {
        BigDecimal b = new BigDecimal(temp);
        double v = b.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        return v;
    }

    public static double roundDouble(double temp, int num) {
        BigDecimal b = new BigDecimal(temp);
        double v = b.setScale(num, BigDecimal.ROUND_HALF_UP).doubleValue();
        return v;
    }

    public static String shaqCrypt(String content) {
        return CryptUtil.hamcsha1(content, "bec354dc3ce44abcb91c1c356512afed");
    }

    public static int doubleToInt(double value) {
        String temp = String.valueOf(value);
        if (temp.contains(".")) {
            int index = temp.indexOf(".");
            temp = temp.substring(0, index);
        }
        return parseInt(temp);
    }

    public static boolean match(String pattern, String text) {

        Pattern p = Pattern.compile(pattern);
        Matcher m = p.matcher(text);
        boolean isMatch = m.matches();
        return isMatch;
    }

    public static String printMap(Map<String, String> map) {
        if (map == null) {
            return "";
        }
        StringBuilder stringBuilder = new StringBuilder();
        Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, String> next = iterator.next();
            stringBuilder.append(next.getKey() + ":" + next.getValue() + " ");
        }
        return stringBuilder.toString();
    }

    public static double parseDouble(String text) {
        if (stringIsBlank(text)) {
            return 0d;
        }
        try {
            return Double.parseDouble(text);
        } catch (NumberFormatException e) {
            return 0d;
        }

    }

    public static String getOrgCode(int adminType,
                                    long parentOrgId, long index) {

        StringBuilder sbf = new StringBuilder();
        sbf.append(adminType + 1);
        for (int i = 0; i < 4 - String.valueOf(parentOrgId).length(); i++) {
            sbf.append("0");
        }
        sbf.append(parentOrgId);

        for (int i = 0; i < 4 - String.valueOf(index).length(); i++) {
            sbf.append("0");
        }
        sbf.append(index);
        return sbf.toString();

    }

    public static String unitByte(long bytes) {
        int unit = 1024;
        int exp = Math.max(0, Math.min((int) (Math.log(bytes) / Math.log(unit)), 3));
        float bytesUnit = (float) (bytes / Math.pow(unit, exp));
        switch (exp) {
            case 0:
                return String.format("%.0f B", bytesUnit);
            case 1:
                return String.format("%.1f KB", bytesUnit);
            case 2:
                return String.format("%.1f MB", bytesUnit);
            default:
                return String.format("%.1f GB", bytesUnit);
        }
    }

    /**
     * 默认密码，登录名后六位
     *
     * @param loginName
     * @return
     */
    public static String buildDefaultPassword(String loginName) {
        String pStr;
        int pswLen = 6;
        if (loginName.length() < pswLen) {
            pStr = "123456";
        } else {
            pStr = loginName.substring(loginName.length() - pswLen);
        }
        String password = DESUtil.encrypt(pStr);
        return MD5Util.MD5(password);
    }


    /**
     * @param graph 有向无环图
     * @return 拓扑排序结果
     */
    public static <T> List<T> topoLogySort(Graph<T> graph) {
        //用一个数组标志所有节点入度
        int[] inDegree = new int[graph.getNodeSize()];
        for (LinkedList list : graph.getAdj()) {
            for (Object index : list) {
                ++inDegree[(int) index];
            }
        }
        //用一个数组标志所有节点是否已经被访问
        boolean[] visited = new boolean[graph.getNodeSize()];
        //开始进行遍历
        Deque<Integer> nodes = new LinkedList<>();
        //将入度为0节点入队
        for (int i = 0; i < graph.getNodeSize(); i++) {
            if (inDegree[i] == 0) {
                nodes.offer(i);
            }
        }
        List<T> result = new ArrayList<>();
        //将入度为0节点一次出队处理
        while (!nodes.isEmpty()) {
            int node = nodes.poll();
            if (visited[node]) {
                continue;
            }
            visited[node] = true;
            result.add(graph.getNode().get(node));
            //将当前node的邻接节点入度-1；
            for (Object list : graph.getAdj()[node]) {
                --inDegree[(int) list];
                if (inDegree[(int) list] == 0) {
                    //前驱节点全部访问完毕，入度为0
                    nodes.offer((int) list);
                }
            }
        }
        return result;
    }

}
